/*
 * Copyright (c) 2021 com.youkeyi. All rights reserved.
 *
 *  @author liuxiawang
 *  @location Shenzhen.China
 *  @date 4/8/21 10:35 PM
 */

package com.youkeyi.ddy.cloud.application.system.login.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youkeyi.ddy.cloud.application.system.login.dto.LoginDto;
import com.youkeyi.ddy.cloud.application.system.login.service.LoginService;
import com.youkeyi.ddy.cloud.common.annotation.PassToken;
import com.youkeyi.ddy.cloud.common.api.application.system.login.SystemLoginFeignService;
import com.youkeyi.ddy.cloud.common.api.application.system.login.param.LoginAuthCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.PublicUserAuthLoginCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.param.PublicUserAuthLoginCreateCloudParam;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyApplicationSystemConstant;
import com.youkeyi.ddy.cloud.common.context.YoukeyiSystemContext;
import com.youkeyi.ddy.cloud.common.enums.ResponseCodeEnum;
import com.youkeyi.ddy.cloud.common.response.ResponseContent;
import com.youkeyi.ddy.cloud.common.response.ResponseObjectContent;
import com.youkeyi.ddy.cloud.common.utils.RedisUtils;
import com.youkeyi.ddy.cloud.common.utils.SecurityUtils;
import com.youkeyi.ddy.cloud.common.utils.SimpleUUidUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录相关
 *
 * @Author liuxiawang
 * @Date 2021-04-08 22:35
 * @Location shenzhen.china
 */
@Service
public class SystemLoginController implements SystemLoginFeignService {

    private static final Logger logger = LoggerFactory.getLogger(SystemLoginController.class);

    @Autowired
    private LoginService loginService;
    @Autowired
    private PublicUserAuthLoginCloudService publicUserAuthLoginCloudService;

//    // 使用公钥加密的测试方法
//    public static void main(String[] args) throws Exception {
//        Map<String, String> map = new HashMap<>();
//        map.put("account", "admin");
//        map.put("password", "zty#19920211*");
//        String content = JSON.toJSONString(map);
//        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZMiq6OseM4A+++WMWEejgA0fvSRNV6HGyWyZe8IjcnPGwJ8PvxAvbCy03O+opRr0WJENG1smoEZ8o7QTF0/x7rzobng3oNSD5w/yS679SwFo/1HmLYYCAYV04VzQ01fE0aADthUkFG7u+bvtiN+xgCMKg7mtHhDOmTB5h9vn8IQIDAQAB";
//        String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJkyKro6x4zgD775YxYR6OADR+9JE1XocbJbJl7wiNyc8bAnw+/EC9sLLTc76ilGvRYkQ0bWyagRnyjtBMXT/HuvOhueDeg1IPnD/JLrv1LAWj/UeYthgIBhXThXNDTV8TRoAO2FSQUbu75u+2I37GAIwqDua0eEM6ZMHmH2+fwhAgMBAAECgYBiCNOE92aJxTzuVkNNdUqUSCU5gIcKG8TegSwN51l97EVSGDBv+AIqO33E8eeIYIdSawROidbkYdp7YyoBuwW/0R3bF7xCojUbQQa2dLXrAdP/hNRbLDt4k/s3Crn+2BGZeW279UZ/hP1a3MjiL70k3yeF4JRvAPDaTcyFLM8mQQJBAPbjewOFJvq7RWeXmcew0Lj0FJOgxZ97RJansPjM6IbWmew9+9I1NeXs2IQzywP4xTXhfM28HxydTtSauFDPbakCQQCe2YKg/wzRh8Za4XzlNN+6ezOa0m+5GsH+b8CsqGtV9MRTr9FPo4UDB2eaomLkoHHht1PsE7/5LVfu0fEeufW5AkB8UfY6wozrSuvbCzrTlFS2HapS4G1DLoZOOqjh0ATzCRM/I8Mvib3XRtmMUKxVFqrvw9jdnHIqLYhphHN1tc3pAkB6M5iTpEJHOu10Yr2DUr6+piLX+wWp4BTXWT9fVB1mver++mXKn2AnKV4hjsUHXwrc+vzbw4HO/nwEJIwa+DI5AkEA7nH7Vcm4RCGmJb4Tk3lxoSjhxFV3YebxXcG7R5qTYklNFhBO8e4aCv5e3iDgD9S/wp4513ROzrzF7kPwQg1ffw==";
//
//        // 公钥加密
//        String encryptyPublicKey = SecurityUtils.rsaEncryptyPublicKey(content, publicKey);
//        System.err.println(encryptyPublicKey);
//        // 私钥解密
//        System.err.println(SecurityUtils.rsaDecryptByPrivateKey(encryptyPublicKey, privateKey));
//    }

//    public static void main(String[] args) {
//        String md5 = SecurityUtils.md5("zty#19920211*", "123455b0d9050323964b47b187f5790a5c0d22");
//        logger.info(md5);
//    }

    @Override
    @PassToken
    public ResponseContent getAuthCode(HttpServletRequest request, HttpServletResponse response) {
        ResponseContent rc = new ResponseContent();

        // 获取加密解密的密钥对，公钥返回给前端，前端加密登录数据后密文给后端
        // 后端通过私钥解密密文获取登录数据
        SecurityUtils.SecurityKey securityKey;
        try {
            securityKey = SecurityUtils.getKey(String.format("%s%s", "LOGIN_CODE", String.valueOf(System.currentTimeMillis())));
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("获取密钥对失败");
            return rc;
        }
        // redis key
        String token = SimpleUUidUtils.getUuid();
        // 构造存储格式
        Map<String, String> loginKeyMap = new HashMap<>();
        loginKeyMap.put(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_PUBLIC_KEY, securityKey.getPublicKey());
        loginKeyMap.put(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_PRIVATE_KEY, securityKey.getPrivateKey());
        try {
            // 将生成的code、私钥、公钥存入redis
            RedisUtils.addHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token, loginKeyMap, YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_CACHE_SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("获取安全码失败");
            return rc;
        }

        rc.setSuccessMessage("获取成功");
        rc.setKey(securityKey.getPublicKey());
        response.setHeader(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_TOKEN_KEY, token);
        return rc;
    }

    @Override
    @PassToken
    public ResponseObjectContent login(HttpServletRequest request, HttpServletResponse response, LoginAuthCloudParam param) {
        ResponseObjectContent<LoginDto> rc = new ResponseObjectContent<>();
        String token = request.getHeader(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_TOKEN_KEY);
        if (StringUtils.isBlank(token)) {
            rc.setErrorMessage("Token缺失");
            return rc;
        }
        if (null == param || StringUtils.isBlank(param.getBodyStr())) {
            rc.setErrorMessage("必输参数缺失");
            return rc;
        }

        Map<String, String> loginKeyMap;
        try {
            loginKeyMap = new HashMap<>(RedisUtils.getHashMapFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token));
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("获取密钥失败");
            return rc;
        }
        if (!loginKeyMap.containsKey(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_PRIVATE_KEY) || StringUtils.isBlank(loginKeyMap.get(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_PRIVATE_KEY))) {
            rc.setErrorMessage("获取私钥失败");
            return rc;
        }

        String account;
        String password;
        try {
            String decryptStr = SecurityUtils.rsaDecryptByPrivateKey(param.getBodyStr(), loginKeyMap.get(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_PRIVATE_KEY));
            logger.info("登录表单数据： {}", decryptStr);
            JSONObject loginData = JSON.parseObject(decryptStr);
            account = loginData.getString("account");
            password = loginData.getString("password");
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("解密失败:" + e.getMessage());
            return rc;
        }
        if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
            rc.setErrorMessage("解密失败");
            return rc;
        }

        LoginDto loginDto = loginService.login(account, password, token, "webApp");
        rc.setData(loginDto);
        rc.setSuccess(loginDto.isSuccess());
        rc.setMessage(loginDto.getMessage());
        return rc;
    }

    @Override
    public ResponseContent logout(HttpServletRequest request, HttpServletResponse response) {
        ResponseContent rc = new ResponseContent();
        String token = request.getHeader(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_TOKEN_KEY);
        try {
            // 清除token
            RedisUtils.delKeyFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token);
            rc.setSuccessMessage("登出成功");
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("登出失败");
        }
        return rc;
    }


    @Override
    @PassToken
    public ResponseContent getAuthorizationLink(HttpServletRequest request, HttpServletResponse response) {
        ResponseContent rc = new ResponseContent();
        // redis key
        String token = SimpleUUidUtils.getUuid();
        // 构造存储格式
        Map<String, String> loginKeyMap = new HashMap<>();
        loginKeyMap.put("authorizationCode", token);
        loginKeyMap.put("authorizationStatus", "NO_AUTHORIZATION");
        loginKeyMap.put("authorizationAccount", "");
        try {
            // 将生成的code、私钥、公钥存入redis
            RedisUtils.addHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, "AUTHORIZATION_CODE_" + token, loginKeyMap, YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_CACHE_SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
            rc.setErrorMessage("获取安全码失败");
            return rc;
        }

        String link = "https://ddy.yoyejia.com/api/system/login/applet/authorization/" + token;
        rc.setSuccessMessage("获取成功");
        rc.setKey(link);
        return rc;
    }

    @Override
    @PassToken
    public ResponseObjectContent authorizationLogin(HttpServletRequest request, HttpServletResponse response, String gid) {
        ResponseObjectContent<LoginDto> rc = new ResponseObjectContent<>();
//        String corpKey = YoukeyiSystemContext.getCorpPrimaryKey();
//        if (StringUtils.isBlank(corpKey)) {
//            rc.setErrorMessage(ResponseCodeEnum.TOKEN_INVALID.getMessage());
//            return rc;
//        }
        if (StringUtils.isBlank(gid)) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }

        Map<String, String> loginKeyMap;
        try {
            loginKeyMap = new HashMap<>(RedisUtils.getHashMapFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, "AUTHORIZATION_CODE_" + gid));
            if (loginKeyMap.size() == 0) {
                rc.setErrorMessage("授权登陆失败!");
                return rc;
            }
        } catch (Exception e) {
            logger.error("gid: " + gid, e);
            rc.setErrorMessage("授权登陆失败!");
            return rc;
        }

        if (!"AUTHORIZATION".equals(loginKeyMap.get("authorizationStatus"))) {
            rc.setSuccessMessage("等待授权!");
            return rc;
        }

        // 授权完成，直接登陆
        String account = loginKeyMap.get("authorizationAccount");
        String token = SimpleUUidUtils.getUuid();
        LoginDto loginDto = loginService.login(account, "", token, "minAppAuth");
        rc.setData(loginDto);
        rc.setSuccess(loginDto.isSuccess());
        rc.setMessage(loginDto.getMessage());
        response.setHeader(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_TOKEN_KEY, token);
        return rc;
    }

    @Override
    public ResponseContent authorization(LoginAuthCloudParam param) {
        ResponseContent rc = new ResponseContent();
        String corpKey = YoukeyiSystemContext.getCorpPrimaryKey();
        if (StringUtils.isBlank(corpKey)) {
            rc.setErrorMessage(ResponseCodeEnum.TOKEN_INVALID.getMessage());
            return rc;
        }
        if (StringUtils.isBlank(param.getGid())) {
            rc.setErrorMessage(ResponseCodeEnum.PARAMETER_ILLEGAL.getMessage());
            return rc;
        }
        String gid = param.getGid();

        Map<String, String> loginKeyMap;
        try {
            loginKeyMap = new HashMap<>(RedisUtils.getHashMapFromJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, "AUTHORIZATION_CODE_" + gid));
            if (loginKeyMap.size() == 0) {
                rc.setErrorMessage("授权失败!");
                return rc;
            }

            // 修改gid里面数据
            loginKeyMap.put("authorizationCode", gid);
            loginKeyMap.put("authorizationStatus", "AUTHORIZATION");
            loginKeyMap.put("authorizationAccount", YoukeyiSystemContext.getUserAccount());
            RedisUtils.addHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, "AUTHORIZATION_CODE_" + gid, loginKeyMap, YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_CACHE_SECONDS);

            // 保存授权记录
            PublicUserAuthLoginCreateCloudParam authLoginCreateCloudParam = new PublicUserAuthLoginCreateCloudParam();
            authLoginCreateCloudParam.setUserKey(YoukeyiSystemContext.getUserPrimaryKey());
            authLoginCreateCloudParam.setUserName(YoukeyiSystemContext.getUserName());
            authLoginCreateCloudParam.setAuthCorpKey(YoukeyiSystemContext.getCorpPrimaryKey());
            authLoginCreateCloudParam.setAuthCorpCoordinate(param.getAuthCorpCoordinate());
            authLoginCreateCloudParam.setAuthAccount(YoukeyiSystemContext.getUserAccount());
            authLoginCreateCloudParam.setAuthPhone(YoukeyiSystemContext.getUserPhone());
            authLoginCreateCloudParam.setAuthTime(System.currentTimeMillis());
            authLoginCreateCloudParam.setCreateUserKey(YoukeyiSystemContext.getUserPrimaryKey());
            authLoginCreateCloudParam.setCreateUserName(YoukeyiSystemContext.getUserName());
            publicUserAuthLoginCloudService.create(authLoginCreateCloudParam);
        } catch (Exception e) {
            logger.error("gid: " + gid, e);
            rc.setErrorMessage("授权失败!");
            return rc;
        }

        rc.setSuccessMessage("授权成功");
        return rc;
    }
}
